<template>
  <div>
    <el-form ref="queryForm" class="query-form"
      :model="queryParams"
      size="small"
      inline>
      <el-form-item label="兑换码名称">
        <el-input v-model="queryParams.keyword" placeholder="请输入兑换码名称"></el-input>
      </el-form-item>
      <el-form-item label="兑换码类型" prop="code_cat">
        <el-select v-model="queryParams.code_cat" placeholder="请选择">
          <el-option label="全部" :value="null" />
          <el-option v-for="([key, value], index) in exchangeCodeTypeOptions" :key="index" :label="value.desc" :value="key" />
        </el-select>
      </el-form-item>
      <el-form-item label="兑换码" prop="code_cat">
        <el-input v-model="queryParams.code" placeholder="兑换码" clearable></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" size="small" @click="handleQuery">搜索</el-button>
        <el-button type="default" size="small" @click="handleResetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-button type="primary"
      icon="el-icon-plus"
      style="margin-bottom:10px"
      size="small"
      @click="handleAdd">新增</el-button>
    <el-table v-loading="listLoading"
      :data="tableData">
      <el-table-column label="编号"
        min-width="60"
        prop="id" />
      <el-table-column label="兑换码名称"
        min-width="150"
        prop="name" />
      <el-table-column label="兑换码类型"
        min-width="100"
        prop="code_cat">
        <template slot-scope="scope">
          {{ exchangeCodeTypeOptions.get(scope.row.code_cat).desc || "-" }}
        </template>
      </el-table-column>
      <el-table-column label="兑换内容"
        min-width="150"
        prop="name">
        <template slot-scope="scope">
          {{scope.row.rel_resource|productNameFilter}}
        </template>
      </el-table-column>
      <el-table-column label="兑换权益"
        min-width="150"
        prop="name">
        <template slot-scope="scope">
          {{scope.row.rel_resource| prdoctRightFilter}}
        </template>
      </el-table-column>
      <el-table-column label="兑换码有效期"
        min-width="200"
        prop="p_icon">
        <template slot-scope="scope">
          {{scope.row.validity_begin}} - {{scope.row.validity_end}}
        </template>
      </el-table-column>
      <el-table-column label="使用限制" min-width="120">
        <template slot-scope="scope">
          {{ scope.row.sg_user_limit?scope.row.sg_user_limit+'次/人':'无限制使用' }}
        </template>
      </el-table-column>
      <el-table-column label="生成数量"
        min-width="120"
        prop="total_amount" />
      <el-table-column label="领取数量"
        min-width="120"
        prop="draw_amount" />
      <el-table-column label="状态" min-width="80">
        <template slot-scope="scope">
          <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'"
            disable-transitions>{{ scope.row.status === 1 ? '启用' : '停用' }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作"
        width="180"
        fixed="right"
        class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="small"
            type="text"
            @click="handleUpdata(scope.row)">{{ scope.row.status === 1 ? '停用' : '启用' }}</el-button>
          <el-button
            size="small"
            type="text"
            @click="handleDetail(scope.row)">详情</el-button>
          <el-button
            size="small"
            type="text"
            @click="handleDelete(scope.row)">删除</el-button>
          <el-button
            size="small"
            type="text"
            v-if="exchangeCodeTypeOptions.get(scope.row.code_cat).customCodes"
            @click="handleEdit(scope.row)">修改</el-button>
        </template>
      </el-table-column>
    </el-table>
    <pagination v-show="total > 0"
      :total="total"
      :page.sync="queryParams.page"
      :limit.sync="queryParams.page_size"
      @pagination="getList" />
    <el-dialog :title="editDialogTitle"
      :visible.sync="addDialogShow"
      width="670px"
      :close-on-click-modal="false">
      <el-form label-width="100px" class="input-form-fill" :model="form" :rules="rules" ref="form">
        <el-form-item label="兑换码名称" prop="name">
          <el-input v-model="form.name" @blur="form.name=$event.target.value.trim()" :disabled="isUpdataInfo"></el-input>
        </el-form-item>
        <el-form-item label="兑换码类型" prop="code_cat">
          <el-select v-model="form.code_cat" placeholder="请选择" @change="exchangeCodeTypeChange" :disabled="isUpdataInfo">
            <el-option v-for="([key, value], index) in exchangeCodeTypeOptions" :key="index" :label="value.desc" :value="key" />
          </el-select>
        </el-form-item>
        <el-form-item label="兑换码权益" prop="rel_resource.type">
          <el-radio-group v-model="form.rel_resource.type" :disabled="isUpdataInfo">
            <el-radio :label="2">权益包</el-radio>
            <el-radio :label="3">加购包</el-radio>
          </el-radio-group>
        </el-form-item>
        <template v-if="form.rel_resource.type===2">
          <el-form-item label="权益包" prop="rel_resource.rel_id">
            <el-select v-model="form.rel_resource.rel_id" placeholder="请选择" @change="handleLevelSelChange('rightPackageOptions')" :disabled="isUpdataInfo">
              <el-option v-for="item in rightPackageOptions" :key="item.package_id" :label="item.name" :value="item.package_id" />
            </el-select>
          </el-form-item>
          <el-form-item label="权益期限" prop="rel_resource.param.duration">
            <el-select v-model="form.rel_resource.param.duration" placeholder="请选择" :disabled="isUpdataInfo">
              <el-option v-for="(item, index) in memberTimeOptions" :key="index" :label="item[1]" :value="item[0]" />
            </el-select>
          </el-form-item>
        </template>
        <template v-else>
          <el-form-item label="数量" prop="">
          <el-col :span="13">
            <el-form-item prop="rel_resource.param.num">
              <el-input v-model="form.rel_resource.param.num" style="width: 100%;" :disabled="isUpdataInfo"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="11">
            <el-form-item prop="rel_resource.param.unit_id">
              <el-select v-model="form.rel_resource.param.unit_id" style="width: 180px;" @change="handleUnitChange()" :disabled="isUpdataInfo">
                <el-option v-for="item in chargeUnitList" :value="item.unit_id" :label="item.internal_name" :key="item.unit_id"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-form-item>
        </template>
        <el-form-item label="设置有效期" prop="validity">
          <el-date-picker v-model="form.validity"
            :disabled="isUpdataInfo"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="生成数量" prop="total_amount" key="total_amount1" v-if="!exchangeCodeTypeOptions.get(form.code_cat).customCodes">
          <el-input v-model.trim.number="form.total_amount" :disabled="isUpdataInfo"></el-input>
        </el-form-item>
        <el-form-item label="使用限制" prop="sg_user_limit" key="sg_user_limit">
          <el-input v-model.trim="form.sg_user_limit" style="width: 150px" :disabled="isUpdataInfo||exchangeCodeTypeOptions.get(form.code_cat).customCodes"></el-input> 次/人（填0代表无限制使用）
        </el-form-item>
        <template v-if="exchangeCodeTypeOptions.get(form.code_cat).customCodes">
        <!-- <el-form-item prop="codes"> -->
          <div v-for="(item,index) in form.codes" :key="item.key" class="code-list">
            <el-form-item label="口令文本" :prop="'codes.'+ index +'.code'" :rules="rules.codes_code">
              <el-input v-model.trim="item.code" style="width: 220px;" />
            </el-form-item>
            <el-form-item label="兑换上限" :prop="'codes.'+ index" :rules="rules.codes_amount">
              <el-input-number v-model="item.amount" :precision="0" :min="0" controls-position="right" style="width: 130px;" />
            </el-form-item>
            <div class="code-toolbar">
              <el-button class="ml10" size="mini" circle @click="onDeleteCodes(index)" :disabled="form.codes.length<2||!!item.old_amount" :title="item.old_amount?'编辑状态下不可删除':''">
                <i class="el-icon-minus"></i>
              </el-button>
              <el-button class="ml10" size="mini" circle @click="onAddCodes(index)">
                <i class="el-icon-plus"></i>
              </el-button>
            </div>
          </div>
        <!-- </el-form-item> -->
        </template>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="onSubmitAdd" :loading="saveLoading">确 认</el-button>
        <el-button @click="addDialogShow = false">取 消</el-button>
      </div>
    </el-dialog>
    <detail-dialog :visible.sync="detailDialogShow" :detailObj="detailObj"/>
  </div>
</template>
<script>
import detailDialog from './components/detail.vue'
import { exchangeCodeList, createExchangeCode, updateExchangeCode, delExchangeCode, exchangeCodeDetail } from '@/api/exchange-code'
import { productList } from '@/api/member/product'
import { listRightPackage } from '@/api/rights/package'
import { getMemberValidTime, getExchangeCodeType } from '@/constants/constant'
import { getChargeUnit } from '@/api/system'
export default {
  name: 'ExchangeCodeList',
  components: {
    detailDialog
  },
  data () {
    const validateCode = (rule, value, callback) => {
      if (!value) {
        callback(new Error('请输入口令文本'))
      } else if (value.length < 6 || value.length > 16) {
        callback(new Error('口令文本长度为6-16位'))
      } else if (!/^[a-zA-Z0-9-]+$/.test(value)) {
        callback(new Error('口令码必须包含“-”，以及字母或数字'))
      } else if (!/-/.test(value)) {
        callback(new Error('口令码必须包含“-”，以及字母或数字'))
      } else if (this.form.codes.filter(({ code }) => code === value).length > 1) {
        callback(new Error('该口令已存在'))
      } else {
        callback()
      }
    }
    const validateCodeAmount = (rule, value, callback) => {
      const { amount, old_amount } = value
      if (!/^[1-9]\d*$/.test(amount)) {
        callback(new Error('请输入正整数'))
      } else if (old_amount && old_amount > amount) {
        callback(new Error('新上限值不能低于当前上限值:' + old_amount))
      } else {
        callback()
      }
    }
    return {
      listLoading: false,
      saveLoading: false,
      addDialogShow: false,
      detailDialogShow: false,
      // 权益包选项
      rightPackageOptions: [],
      // 权益期限选项
      memberTimeOptions: undefined,
      // 口令码选项
      exchangeCodeTypeOptions: undefined,
      chargeUnitList: [],
      queryParams: {
        code_cat: null,
        page: 1,
        page_size: 20,
        keyword: '',
        code: ''
      },
      form: {
        'name': '', // 优惠券名称
        // 'product': null, // 时长卡 [id]
        'validity': null, // 有效期时间范围 【用于输入】
        'total_amount': '', // 总数量
        sg_user_limit: '', // 使用限制
        code_cat: 1,
        status: 1, // 状态
        rel_resource: {
          type: 2,
          rel_id: '',
          param: {
            name: '',
            duration: null,
            num: '',
            unit_id: null
          }
        },
        codes: [
          { key: Date.now(), code: '', amount: undefined }
        ]
      },
      productData: [],
      tableData: [],
      total: 0,
      detailObj: {},
      rules: {
        name: [
          { required: true, message: '请输入兑换码名称', trigger: 'blur' }
        ],
        code_cat: [
          { required: true, message: '兑换码类型不能为空', trigger: 'change' }
        ],
        'rel_resource.rel_id': [
          { required: true, message: '权益包不能为空', trigger: 'change' }
        ],
        'rel_resource.param.duration': [
          { required: true, message: '权益期限不能为空', trigger: 'change' }
        ],
        'rel_resource.param.num': [
          { required: true, pattern: /^\d+$/, message: '请输入整数', trigger: 'blur' }
        ],
        'rel_resource.param.unit_id': [
          { required: true, message: '不能为空', trigger: 'change' }
        ],
        validity: [
          { required: true, type: 'array', message: '有效期不能为空', trigger: 'change' }
        ],
        total_amount: [
          { required: true, pattern: /^\d+$/, message: '请输入整数', trigger: 'blur' },
          { type: 'integer', max: 1000, message: '生成数量不能大于1000', trigger: 'blur' }
        ],
        sg_user_limit: [
          { required: true, pattern: /^\d+$/, message: '请输入整数', trigger: 'blur' }
        ],
        codes: [
          { required: true, type: 'array', message: '口令码不得为空', trigger: 'blur' }
        ],
        codes_code: [
          { required: true, validator: validateCode, trigger: 'blur' }
        ],
        codes_amount: [
          { required: true, validator: validateCodeAmount, trigger: 'blur' }
        ]
      }

    }
  },
  computed: {
    isUpdataInfo () {
      return !!this.form.id
    },
    editDialogTitle () {
      return this.isUpdataInfo ? '修改兑换码' : '新增兑换码'
    }
  },
  filters: {
    productNameFilter (val) {
      const item = val?.[0] || {}
      if (item.type === 3) return '加购包'
      return item.name || '--'
      // const arr = []
      // for (const item of val) {
      //   if (item.type === 1 || item.type === 2 || item.type === 3) arr.push(item.name)
      // }
      // return arr.join('，') || '--'
    },
    prdoctRightFilter (val) {
      const item = val?.[0] || {}
      let param = item?.param || '{}'
      try {
        param = JSON.parse(param)
      } catch (error) {
        console.log(error)
      }
      if (item.type === 3) return param.name
      const duration = param.duration || 0
      const target = [...getMemberValidTime()].find(v => v[0] === duration)
      return target ? target[1] : '--'
      // return extText(param.duration, param.unlimited)
    }
  },
  created () {
    this.getList()
    listRightPackage({ page: 1, page_size: 100, status: 1 }).then(res => {
      this.rightPackageOptions = res.data.list || []
    })
    getChargeUnit().then(res => {
      this.chargeUnitList = res.data.list
    })
    this.memberTimeOptions = getMemberValidTime()
    this.exchangeCodeTypeOptions = getExchangeCodeType()
    // this.getProductOps()
  },
  methods: {
    getProductOps (keyword = '') {
      const param = {
        status: 10,
        page: 1,
        page_size: 1000,
        keyword: keyword.trim()
      }
      productList(param).then(res => {
        this.productData = res.data.list || []
      })
    },
    handleQuery () {
      this.queryParams.page = 1
      this.getList()
    },
    handleResetQuery () {
      this.queryParams = {
        code_cat: null,
        page: 1,
        page_size: 20,
        keyword: '',
        code: ''
      }
      this.getList()
    },
    getList () {
      this.listLoading = true
      exchangeCodeList(this.queryParams).then(res => {
        const data = res.data || {}
        this.tableData = data.list || []
        this.total = data.count
      }).finally(() => {
        this.listLoading = false
      })
    },
    /** 权益下拉框操作 */
    handleLevelSelChange (type) {
      const list = this[type]
      if (!Array.isArray(list)) return
      const selLevel = list.find(item => item.package_id === this.form.rel_resource.rel_id) || {}
      console.log(selLevel)
      this.form.rel_resource.param.name = selLevel.name
    },
    handleUnitChange () {
      const selLevel = this.chargeUnitList.find(item => item.unit_id === this.form.rel_resource.param.unit_id) || {}
      this.form.rel_resource.param.name = selLevel.name
    },
    handleUpdata (row) {
      const cStatus = row.status ? 0 : 1
      const cStatusText = row.status === 1 ? '停用' : '启用'
      this.$confirm(`是否${cStatusText}“${row.name}?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        updateExchangeCode({
          id: row.id,
          status: cStatus
        }).then(() => {
          this.$message({
            type: 'success',
            message: cStatusText + '成功!'
          })
          row.status = cStatus
        }).catch(e => {
          this.showErrMsg(e)
        })
      })
    },
    handleAdd () {
      this.form = {
        'name': '', // 优惠券名称
        // 'product': null, // 时长卡 [id]
        'validity': null, // 有效期时间范围 【用于输入】
        'total_amount': '', // 总数量
        sg_user_limit: '', // 使用限制
        code_cat: 1,
        status: 1, // 状态
        rel_resource: {
          type: 2,
          rel_id: '',
          param: {
            name: '',
            duration: null,
            num: '',
            unit_id: null
          }
        },
        codes: [
          { key: Date.now(), code: '', amount: undefined }
        ]
      }
      this.$nextTick(() => {
        this.$refs.form && this.$refs.form.clearValidate()
      })
      this.addDialogShow = true
    },
    handleDetail (row) {
      this.detailObj = row
      this.detailDialogShow = true
    },
    handleDelete (row) {
      this.$confirm(`此操作将永久删除”${row.name}“, 是否继续?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        delExchangeCode({ id: row.id }).then(() => {
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          this.getList()
        })
      })
    },
    async handleEdit (row) {
      const res = await exchangeCodeDetail({ id: row.id })
      if (!res.data) {
        this.$message('信息加载失败')
        return
      }
      row = res.data

      this.addDialogShow = true
      this.$nextTick(() => {
        const rel_resource = row.rel_resource[0] || {}
        let rel_resource_param
        try {
          rel_resource_param = JSON.parse(rel_resource.param)
        } catch (e) {
          rel_resource_param = {}
        }
        const newData = {
          id: row.id,
          name: row.name,
          validity: [ row.validity_begin, row.validity_end ],
          total_amount: row.total_amount,
          sg_user_limit: row.sg_user_limit,
          code_cat: row.code_cat,
          status: row.status,
          rel_resource: {
            type: rel_resource.type,
            rel_id: rel_resource.id,
            param: {
              name: rel_resource_param.name,
              duration: rel_resource_param.duration,
              num: rel_resource_param.num,
              unit_id: rel_resource_param.unit_id
            }
          },
          codes: (row.codes || []).map(({ code, amount }, i) => ({ key: i, code, amount, old_amount: amount }))
        }
        if (!newData.codes.length) {
          newData.codes.push({ key: Date.now(), code: '', amount: undefined })
        }
        this.form = newData

        this.$nextTick(() => {
          this.$refs.form && this.$refs.form.clearValidate()
        })
      })
    },
    exchangeCodeTypeChange (val) {
      if (this.exchangeCodeTypeOptions.get(val).customCodes) {
        this.form.sg_user_limit = 1
      }
    },
    onAddCodes (idx = 0) {
      const maxCount = 100
      if (this.form.codes.length >= maxCount) {
        return this.$message.error('口令文本数量最多为' + maxCount + '个')
      }
      // this.form.codes.push(
      //   { key: Date.now(), code: '', amount: undefined }
      // )
      this.form.codes.splice(
        idx + 1,
        0,
        { key: Date.now(), code: '', amount: undefined }
      )
    },
    onDeleteCodes (idx) {
      this.form.codes.splice(idx, 1)
    },
    onSubmitAdd () {
      this.$refs.form.validate(valid => {
        if (valid) {
          if (this.isUpdataInfo) {
            this.submitEdit()
            return
          }
          this.saveLoading = true
          let rel_resource = null
          const params = {
            name: this.form.name,
            code_cat: this.form.code_cat,
            // product: [this.form.product],
            sg_user_limit: Number(this.form.sg_user_limit),
            // total_amount: Number(this.form.total_amount),
            status: this.form.status,
            validity_begin: this.form.validity[0],
            validity_end: this.form.validity[1]
          }
          if (this.form.rel_resource.type === 2) {
            rel_resource = {
              type: 2,
              rel_id: this.form.rel_resource.rel_id,
              param: JSON.stringify({
                unlimited: this.form.rel_resource.param.duration === 36792000,
                name: this.form.rel_resource.param.name,
                duration: this.form.rel_resource.param.duration
              })
            }
          } else {
            rel_resource = {
              type: 3,
              param: JSON.stringify({
                name: this.form.rel_resource.param.num + this.form.rel_resource.param.name,
                num: Number(this.form.rel_resource.param.num),
                unit_id: this.form.rel_resource.param.unit_id
              })
            }
          }
          params.rel_resource = rel_resource

          if (this.exchangeCodeTypeOptions.get(this.form.code_cat).customCodes) {
            params['codes'] = this.form.codes.map(({ code, amount }) => ({ code, amount }))
            params['total_amount'] = 0
          } else {
            params['total_amount'] = Number(this.form.total_amount)
          }
          createExchangeCode(params).then(() => {
            this.getList()
            this.$message({
              type: 'success',
              message: '创建成功'
            })
            this.addDialogShow = false
          }).catch(e => {
            this.showErrMsg(e)
          }).finally(() => {
            this.saveLoading = false
          })
        }
      })
    },
    submitEdit () {
      this.saveLoading = true
      const params = {
        id: this.form.id
      }
      if (this.exchangeCodeTypeOptions.get(this.form.code_cat).customCodes) {
        params['codes'] = this.form.codes.map(({ code, amount }) => ({ code, amount }))
      }
      updateExchangeCode(params).then((e) => {
        this.getList()
        this.$message({
          type: 'success',
          message: '修改成功'
        })
        this.addDialogShow = false
      }).catch(e => {
        this.showErrMsg(e)
      }).finally(() => {
        this.saveLoading = false
      })
    },
    showErrMsg (err) {
      const errMap = {}
      const { code_errors: errData = {} } = (err && err.data && err.data.data) || {}
      for (let codeKey in errData) {
        const errArr = errData[codeKey]
        for (let errInfo of errArr) {
          errMap[errInfo.error_code] || (errMap[errInfo.error_code] = { msg: errInfo.error_msg, list: [] })
          errMap[errInfo.error_code].list.push(codeKey)
        }
      }

      const h = this.$createElement
      const nodes = Object.keys(errMap).map(i => {
        const { msg, list } = errMap[i]
        return h('div', { style: `margin-bottom: 10px;` }, [
          h('div', { style: `margin-bottom: 5px;` }, msg + '：'),
          h('div', null, list.join('、'))
        ])
      })
      nodes.length && this.$msgbox({
        title: '提示',
        message: h('div', { style: `max-height: 500px;overflow: auto;` }, nodes),
        showCancelButton: true,
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.code-list{
  display: flex;
  align-items: flex-start;
  /deep/.el-form-item__error{
    white-space: nowrap;
  }
}
.code-toolbar{
  padding-top: 3px;
  flex-shrink: 0;
}
</style>
